use chrono::Local;
use crate::db::service::im_message_service::ImMessageService;
use crate::business::app_state::AppState;
use crate::business::rpc::service::rpc_pull_message_service::RpcPullMessageService;
use crate::business::websocket::dto::im_base_dto::CollectInfoItem;
use crate::business::websocket::dto::im_message_dto::{MessageObject, MessagePullByMessageIdsReq};

pub struct MessageRefService;

impl MessageRefService {

    pub async fn pull_collect_ref_messages(app_state: AppState, user_id: String, collect_info_items: &Vec<CollectInfoItem>)->Vec<MessageObject> {
        let server_id_list = collect_info_items.iter().map(|item| item.server_id.clone()).collect::<Vec<_>>();
        MessageRefService::pull_messages(app_state.clone(), user_id, server_id_list).await
    }

    pub async fn pull_messages(app_state: AppState, user_id: String, server_id_list: Vec<String>)->Vec<MessageObject> {
        if server_id_list.is_empty() { return vec![]; }

        let server_id_list2 = server_id_list.iter().map(String::as_str).collect::<Vec<&str>>();

        let message_service = ImMessageService;
        let db_messages = message_service.query_message_by_server_ids(&user_id, server_id_list2);
        let db_id_set = db_messages.iter().map(|message| message.server_id.clone().unwrap()).collect::<Vec<String>>();

        let need_pull_server_id_list = server_id_list.iter().map(|server_id| server_id.clone())
            .filter(|server_id| !db_id_set.contains(server_id))
            .collect::<Vec<String>>();

        if need_pull_server_id_list.is_empty() { return vec![]; }

        let message_pull_by_server_id_req = MessagePullByMessageIdsReq{
            server_message_id_list: need_pull_server_id_list,
            create_date_time: Local::now(),
            local_seq: "".to_string(),
        };

        let mut pull_result = vec![];

        let rpc_message_service = RpcPullMessageService;
        let result = rpc_message_service.pull_message_by_message_ids(app_state.clone(), message_pull_by_server_id_req).await;
        match result {
            Ok(message_object_list) => {
                let ref_server_id_list = message_object_list.message_object_list.iter().filter(|message_object| message_object.ref_message_ids.is_some())
                    .map(|message_object| message_object.server_id.clone().unwrap()).collect::<Vec<String>>();
                if !ref_server_id_list.is_empty() {
                    pull_result.extend(message_object_list.message_object_list);

                    let new_result = Box::pin(MessageRefService::pull_messages(app_state.clone(), user_id.clone(), ref_server_id_list)).await;
                    pull_result.extend(new_result);
                }
            }
            Err(_) => {}
        }

        pull_result
    }
}